package com.itheima.app.manager;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.domain.db.Report;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Option;
import com.itheima.domain.mongo.Question;
import com.itheima.domain.mongo.Questionnaire;
import com.itheima.pojo.Answer;
import com.itheima.pojo.Dimension;
import com.itheima.pojo.SimilarYou;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.QuestionnaireService;
import com.itheima.service.mongo.OptionService;
import com.itheima.service.mongo.QuestionService;
import com.itheima.service.db.ReportService;
import com.itheima.vo.*;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

@Component
public class SoulManager {
    @DubboReference
    private QuestionnaireService questionnaireService;
    @DubboReference
    private ReportService reportService;
    @DubboReference
    private QuestionService questionService;
    @DubboReference
    private OptionService optionService;
    @DubboReference
    private UserInfoService userInfoService;


    public ResponseEntity testSoul() {
        Integer star=2;//用户的干饭能力
        Long userId = UserHolder.get().getId();
        //目的是为了展示全部的问卷，所以要返回问卷的集合
        List<Questionnaire> questionnaires = questionnaireService.findAll();
        List<QuestionnaireVo> questionnaireVos = new ArrayList<>();
        /*遍历每一个问卷，首先把问卷内容封装进去，其次找出问卷对应的题目，
          其次找出题目对应的选项，把内容全部封装进去，然后再查找用户有没有报告，
          如果存在报告，则查看报告中的等级，如果等级低于该试卷，则将该展示试卷VO锁住（Lock=1）
         */
        if (CollectionUtil.isNotEmpty(questionnaires))
            for (Questionnaire questionnaire : questionnaires) {
                QuestionnaireVo questionnaireVo = new QuestionnaireVo();
                questionnaireVo.setCover(questionnaire.getCover());
                questionnaireVo.setId(questionnaire.getId().toHexString());
                questionnaireVo.setLevel(questionnaire.getLevel());
                questionnaireVo.setName(questionnaire.getName());
                questionnaireVo.setStar(questionnaire.getStar());
                //通过问卷id找出对应的问题集合
                List<Question> questionList = questionService.findListByQuestionnaireId(questionnaire.getId());
                List<QuestionVo> questionVos = new ArrayList<>();
                if (CollectionUtil.isNotEmpty(questionList))
                    for (Question question : questionList) {
                        //取出每个问题对应的选项
                        List<Option> optionList = optionService.findListByQuestionId(question.getId());
                        List<OptionVo> optionVos = new ArrayList<OptionVo>();
                        //封装选项VO
                        for (Option option : optionList) {
                            OptionVo optionVo = new OptionVo();
                            optionVo.setId(option.getId().toHexString());
                            optionVo.setOption(option.getOption());
                            optionVos.add(optionVo);
                        }
                        OptionVo[] optionVoArray = new OptionVo[optionVos.size()];
                        optionVoArray = optionVos.toArray(optionVoArray);
                        QuestionVo questionVo = new QuestionVo();
                        questionVo.setOptions(optionVoArray);
                        questionVo.setQuestion(question.getQuestion());
                        questionVo.setId(question.getId().toHexString());


                        questionVos.add(questionVo);
                    }
                //设置问题加选项到问卷里
                QuestionVo[] questionVoArray = new QuestionVo[questionVos.size()];
                questionVoArray = questionVos.toArray(questionVoArray);
                questionnaireVo.setQuestions(questionVoArray);
                Report report = reportService.findByUserIdAndQuestionnaireId(userId,questionnaire.getId().toHexString());
                //接下来查找用户的做试卷能力星级
                if (report == null) {
                    questionnaireVo.setReportId(null);
                    star= star >2?star:2;
                } else {
                    questionnaireVo.setReportId(String.valueOf(report.getId()));
                    star = star>report.getStar()?star:report.getStar();
                }
                //如果用户做试卷能力还没有试卷星级大则锁
                if (questionnaire.getStar() > star)
                    questionnaireVo.setIsLock(1);
                else
                    questionnaireVo.setIsLock(0);
                questionnaireVos.add(questionnaireVo);
            }
        return ResponseEntity.ok(questionnaireVos);
    }

    public ResponseEntity commitQuestionnaire(List<Answer> answers) {

        Integer score = 0;
        String questionId=null;
        StringBuilder stringBuilder = new StringBuilder();
        for (Answer answer : answers) {
            //取出其中一个问题，每个问题都有对应的试卷id，就知道现在在做哪套试卷,应该不会为null，毕竟你开始做试卷肯定有题目
            //如果没有题目你也进不来，那就为null，为null应该查找返回就是null，等待测试bug好了
            questionId = answer.getQuestionId();
            break;
        }
        //取出每一个问题以及选项
        for (Answer answer : answers) {
            String optionId = answer.getOptionId();
            stringBuilder.append(optionId).append(",");
            Option option = optionService.findById(optionId);
            //把每一次选择的得分加上
            score = score + option.getScore();
        }
        String optionIds = stringBuilder.toString();
        if (optionIds.endsWith(","))
            optionIds = optionIds.substring(0, optionIds.length() - 1);


        //目前获取了用户答题的全部得分，准备统计结果
        Long userId = UserHolder.get().getId();
        Question question = questionService.findById(questionId);
    Questionnaire questionnaire=  questionnaireService.findById(question.getQuestionnaireId());
    //根据做的题目获取对应的试卷，获取对应的试卷难度，获取对应试卷id，以便生成对应的报告
        Report report = reportService.findByUserIdAndQuestionnaireId(userId,questionnaire.getId().toHexString());
        boolean isNew = false;
        if (report == null) {
            isNew = true;
            report = new Report();
            report.setUserId(userId);
            report.setStar(questionnaire.getStar());
        }
        report.setUserId(UserHolder.get().getId());
        report.setScore(score);
        //这里统计解锁如果想改进可以用枚举，好像没必要算了，之后再看看吧
        //为什么试卷的难度这么玄学
        switch (report.getStar()) {
            case 2:
                report.setStar(5);
                break;
            case 5:
                report.setStar(7);
                break;
            case 7:
                break;
            default:
                break;
        }
        //这里不判断维护影响评价，就光判断总分
        if (score < 21) {
            report.setCover("https://reggie-pointeat.oss-cn-beijing.aliyuncs.com/images/2022/01/18/1642493125942.jpg");
            report.setConclusion("猫头鹰：他们的共同特质为重计划、条理、细节精准。在行为上，表现出喜欢理性思考与分析、较重视制度、结构、规范。他们注重执行游戏规则、循规蹈矩、巨细靡遗、重视品质、敬业负责。");
        } else if (score < 40) {
            report.setCover("https://reggie-pointeat.oss-cn-beijing.aliyuncs.com/images/2022/01/03/1641196466431.jpg");
            report.setConclusion("白兔型：平易近人、敦厚可靠、避免冲突与不具批判性。在行为上，表现出不慌不忙、冷静自持的态度。他们注重稳定与中长程规划，现实生活中，常会反思自省并以和谐为中心，即使面对困境，亦能泰然自若，从容应付。");
        } else if (score < 55) {
            report.setCover("https://reggie-pointeat.oss-cn-beijing.aliyuncs.com/images/2022/01/05/1641368447337.jpg");
            report.setConclusion("狐狸型 ：人际关系能力极强，擅长以口语表达感受而引起共鸣，很会激励并带动气氛。他们喜欢跟别人互动，重视群体的归属感，基本上是比较「人际导向」。由于他们富同理心并乐于分享，具有很好的亲和力，在服务业、销售业、传播业及公共关系等领域中，狐狸型的领导者都有很杰出的表现。");
        } else {
            report.setCover("https://reggie-pointeat.oss-cn-beijing.aliyuncs.com/images/2022/01/05/src%3Dhttp___inews.gtimg.com_newsapp_bt_0_13391798213_641.jpg%26refer%3Dhttp___inews.gtimg.jpg");
            report.setConclusion("狮子型：性格为充满自信、竞争心强、主动且企图心强烈，是个有决断力的领导者。一般而言，狮子型的人胸怀大志，勇于冒险，看问题能够直指核心，并对目标全力以赴。" +
                    "他们在领导风格及决策上，强调权威与果断，擅长危机处理，此种性格最适合开创性与改革性的工作。");
        }
        //通过问题id找到试卷id，然后把试卷id封装到报告里面用以区分
        report.setQuestionnaireId(question.getQuestionnaireId().toHexString());
        report.setOptionIds(optionIds);
        Long reportId = reportService.save(report, isNew);

        return ResponseEntity.ok(String.valueOf(reportId));
    }


    public ResponseEntity reportById(Long reportId) {
        Integer abstractScore = 0;
        Integer judgeScore = 0;
        Integer logicalScore = 0;
        Integer outScore = 0;
        //展示要展示各个维度，然后不能造假就自己写吧
        Report report = reportService.findById(reportId);
        //取出测灵魂的分数，用于匹配相似用户
        Integer score = report.getScore();
        //调用服务找出相似用户
        //首先说一下，我这边传的集合已经按照相似分数排好序了，这边前端瞎搞我不管。。。
        List<Long> similarIds = reportService.findSimilarYou(score, UserHolder.get().getId(),report.getQuestionnaireId());
        //调用UserInfo找出相似用户信息并封装
        ArrayList<SimilarYou> similarYous = new ArrayList<>();
        for (Long similarId : similarIds) {
            UserInfo userInfo = userInfoService.findById(similarId);
            SimilarYou similarYou = new SimilarYou();
            similarYou.setAvatar(userInfo.getAvatar());
            similarYou.setId(userInfo.getId());
            similarYous.add(similarYou);
        }
        String[] optionIds = report.getOptionIds().split(",");
        //取出报告里面的选项，然后选项有得分，可以获取各个特性的总分
        for (String optionId : optionIds) {
            Option option = optionService.findById(optionId);
            logicalScore = logicalScore + option.getAbstractScore();
            judgeScore = judgeScore + option.getJudgeScore();
            abstractScore = abstractScore + option.getLogicalScore();
            outScore = outScore + option.getOutScore();
        }
        //人家参数要这么传，我已经吐了
        ArrayList<DimensionVo> dimensions = new ArrayList<>();
        DimensionVo abstractdimension = new DimensionVo("抽象", abstractScore+"%");
        DimensionVo judgedimension = new DimensionVo("判断", judgeScore+"%");
        DimensionVo logicaldimension = new DimensionVo("逻辑", logicalScore+"%");
        DimensionVo outdimension = new DimensionVo("外观", outScore+"%");
        dimensions.add(abstractdimension);
        dimensions.add(judgedimension);
        dimensions.add(logicaldimension);
        dimensions.add(outdimension);
        DimensionVo[] dimensionsVoArray = dimensions.toArray(new DimensionVo[0]);
        ReportVo reportVo = new ReportVo();
        reportVo.setDimensions(dimensionsVoArray);
        reportVo.setConclusion(report.getConclusion());
        reportVo.setCover(report.getCover());
        reportVo.setSimilarYou(similarYous.toArray(new SimilarYou[0]));
        return ResponseEntity.ok(reportVo);
    }
}
